# yield 的作用
#如果想要生成斐波那契數列.

# 简单实现
def fab(max):
    n,a,b = 0,0,1
    while n < max:
        print(b)
        a,b=b,a+b
        n = n +1

# 上面的无法复用返回值, 优化后,如下:
def fab2(max):
    n,a,b = 0,0,1
    l = []
    while n < max:
        l.append(b)
        a,b=b,a+b
        n = n +1
    return l

# 上面的如果是巨大的数字, 会占用大量的内存.  我们可以利用iterable 对象来控制内存
class Fab(object):
    def __init__(self,max):
        self.max = max
        self.n,self.a,self.b = 0,0,1

    def __iter__(self):
        return self

    def next(self):
        if self.n < self.max:
            r = self.b
            self.a,self.b = self.b,self.a+self.b
            self.n = self.n + 1
            return r
        raise StopIteration()

# 上面的代码太复杂, 用yield来简化代码, 起到同样的效果
def fab(max):
    n,a,b = 0,0,1
    while n < max:
        yield b
        a,b=b,a+b
        n = n +1
x=Fab(5)
#print(x.next())
#print(x.next())

# 1.10 : 去除序列中出现的重复元素,但仍保持剩下的元素顺序不变
a = [1,5,2,2,1,9,5,10]
b = [{'x':1,'y':2},{'x':3,'y':3},{'x':1,'y':2},{'x':2,'y':2}]
def dedupe(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item # TODO 为啥这里用迭代器就可以不改变顺序. 不用迭代器顺序会变?
            seen.add(item)
# 不可哈希的对象序列中去除重复项, 需要改动如下:
def dedupe2(items,key=None):
    seen =set()
    for item in items:
        val = item if key is None else key(item)
        if val not in seen:
            yield item
            seen.add(val)  #作为临时比较的对象, 判断是否已存在

X=dedupe2(b,key=lambda d:(d['x'],d['y']))
print(X.__next__())
print(X.__next__())
print(X.__next__())